package org.wheel.plugins.toolkit.sql.spi;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import org.wheel.plugins.toolkit.sql.plugin.FunctionPlugin;
import org.wheel.plugins.toolkit.sql.plugin.RulePlugin;

import java.util.List;
import java.util.Map;
import java.util.ServiceLoader;

/**
 * SPI 插件加载器 – 单例 + 线程安全
 * 支持：FunctionPlugin、RulePlugin
 */
public final class PluginLoader {

    private static final PluginLoader INSTANCE = new PluginLoader();

    private final Map<String, FunctionPlugin> functionCache = MapUtil.newConcurrentHashMap();
    private final Map<String, RulePlugin> ruleCache = MapUtil.newConcurrentHashMap();

    private PluginLoader() {
        loadAll();
    }

    public static PluginLoader getInstance() {
        return INSTANCE;
    }

    /**
     * 首次加载所有插件（仅一次）
     */
    private void loadAll() {
        // 1. 函数插件
        ServiceLoader<FunctionPlugin> funcLoader = ServiceLoader.load(FunctionPlugin.class);
        for (FunctionPlugin plugin : funcLoader) {
            functionCache.put(plugin.name(), plugin);
        }

        // 2. 规则插件
        ServiceLoader<RulePlugin> ruleLoader = ServiceLoader.load(RulePlugin.class);
        for (RulePlugin plugin : ruleLoader) {
            ruleCache.put(plugin.name(), plugin);
        }
    }

    /**
     * 获取函数插件
     */
    public FunctionPlugin getFunction(String name) {
        FunctionPlugin plugin = functionCache.get(name);
        if (plugin == null) {
            throw new IllegalArgumentException("未注册函数插件: " + name);
        }
        return plugin;
    }

    /**
     * 获取规则插件
     */
    public RulePlugin getRule(String name) {
        RulePlugin plugin = ruleCache.get(name);
        if (plugin == null) {
            throw new IllegalArgumentException("未注册规则插件: " + name);
        }
        return plugin;
    }

    /**
     * 获取所有函数插件（只读）
     */
    public List<FunctionPlugin> listFunctions() {
        return CollUtil.newArrayList(functionCache.values());
    }

    /**
     * 获取所有规则插件（只读）
     */
    public List<RulePlugin> listRules() {
        return CollUtil.newArrayList(ruleCache.values());
    }

    /**
     * 可选：热重载（开发环境）
     */
    public void reload() {
        functionCache.clear();
        ruleCache.clear();
        loadAll();
    }
}